home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / pr_exec.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  12KB  |  669 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. #include "quakedef.h"
  22.  
  23.  
  24. /*
  25.  
  26. */
  27.  
  28. typedef struct
  29. {
  30.     int                s;
  31.     dfunction_t        *f;
  32. } prstack_t;
  33.  
  34. #define    MAX_STACK_DEPTH        32
  35. prstack_t    pr_stack[MAX_STACK_DEPTH];
  36. int            pr_depth;
  37.  
  38. #define    LOCALSTACK_SIZE        2048
  39. int            localstack[LOCALSTACK_SIZE];
  40. int            localstack_used;
  41.  
  42.  
  43. qboolean    pr_trace;
  44. dfunction_t    *pr_xfunction;
  45. int            pr_xstatement;
  46.  
  47.  
  48. int        pr_argc;
  49.  
  50. char *pr_opnames[] =
  51. {
  52. "DONE",
  53.  
  54. "MUL_F",
  55. "MUL_V", 
  56. "MUL_FV",
  57. "MUL_VF",
  58.  
  59. "DIV",
  60.  
  61. "ADD_F",
  62. "ADD_V", 
  63.   
  64. "SUB_F",
  65. "SUB_V",
  66.  
  67. "EQ_F",
  68. "EQ_V",
  69. "EQ_S", 
  70. "EQ_E",
  71. "EQ_FNC",
  72.  
  73. "NE_F",
  74. "NE_V", 
  75. "NE_S",
  76. "NE_E", 
  77. "NE_FNC",
  78.  
  79. "LE",
  80. "GE",
  81. "LT",
  82. "GT", 
  83.  
  84. "INDIRECT",
  85. "INDIRECT",
  86. "INDIRECT", 
  87. "INDIRECT", 
  88. "INDIRECT",
  89. "INDIRECT", 
  90.  
  91. "ADDRESS", 
  92.  
  93. "STORE_F",
  94. "STORE_V",
  95. "STORE_S",
  96. "STORE_ENT",
  97. "STORE_FLD",
  98. "STORE_FNC",
  99.  
  100. "STOREP_F",
  101. "STOREP_V",
  102. "STOREP_S",
  103. "STOREP_ENT",
  104. "STOREP_FLD",
  105. "STOREP_FNC",
  106.  
  107. "RETURN",
  108.   
  109. "NOT_F",
  110. "NOT_V",
  111. "NOT_S", 
  112. "NOT_ENT", 
  113. "NOT_FNC", 
  114.   
  115. "IF",
  116. "IFNOT",
  117.   
  118. "CALL0",
  119. "CALL1",
  120. "CALL2",
  121. "CALL3",
  122. "CALL4",
  123. "CALL5",
  124. "CALL6",
  125. "CALL7",
  126. "CALL8",
  127.   
  128. "STATE",
  129.   
  130. "GOTO", 
  131.   
  132. "AND",
  133. "OR", 
  134.  
  135. "BITAND",
  136. "BITOR"
  137. };
  138.  
  139. char *PR_GlobalString (int ofs);
  140. char *PR_GlobalStringNoContents (int ofs);
  141.  
  142.  
  143. //=============================================================================
  144.  
  145. /*
  146. =================
  147. PR_PrintStatement
  148. =================
  149. */
  150. void PR_PrintStatement (dstatement_t *s)
  151. {
  152.     int        i;
  153.     
  154.     if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
  155.     {
  156.         Con_Printf ("%s ",  pr_opnames[s->op]);
  157.         i = strlen(pr_opnames[s->op]);
  158.         for ( ; i<10 ; i++)
  159.             Con_Printf (" ");
  160.     }
  161.         
  162.     if (s->op == OP_IF || s->op == OP_IFNOT)
  163.         Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b);
  164.     else if (s->op == OP_GOTO)
  165.     {
  166.         Con_Printf ("branch %i",s->a);
  167.     }
  168.     else if ( (unsigned)(s->op - OP_STORE_F) < 6)
  169.     {
  170.         Con_Printf ("%s",PR_GlobalString(s->a));
  171.         Con_Printf ("%s", PR_GlobalStringNoContents(s->b));
  172.     }
  173.     else
  174.     {
  175.         if (s->a)
  176.             Con_Printf ("%s",PR_GlobalString(s->a));
  177.         if (s->b)
  178.             Con_Printf ("%s",PR_GlobalString(s->b));
  179.         if (s->c)
  180.             Con_Printf ("%s", PR_GlobalStringNoContents(s->c));
  181.     }
  182.     Con_Printf ("\n");
  183. }
  184.  
  185. /*
  186. ============
  187. PR_StackTrace
  188. ============
  189. */
  190. void PR_StackTrace (void)
  191. {
  192.     dfunction_t    *f;
  193.     int            i;
  194.     
  195.     if (pr_depth == 0)
  196.     {
  197.         Con_Printf ("<NO STACK>\n");
  198.         return;
  199.     }
  200.     
  201.     pr_stack[pr_depth].f = pr_xfunction;
  202.     for (i=pr_depth ; i>=0 ; i--)
  203.     {
  204.         f = pr_stack[i].f;
  205.         
  206.         if (!f)
  207.         {
  208.             Con_Printf ("<NO FUNCTION>\n");
  209.         }
  210.         else
  211.             Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name);        
  212.     }
  213. }
  214.  
  215.  
  216. /*
  217. ============
  218. PR_Profile_f
  219.  
  220. ============
  221. */
  222. void PR_Profile_f (void)
  223. {
  224.     dfunction_t    *f, *best;
  225.     int            max;
  226.     int            num;
  227.     int            i;
  228.     
  229.     num = 0;    
  230.     do
  231.     {
  232.         max = 0;
  233.         best = NULL;
  234.         for (i=0 ; i<progs->numfunctions ; i++)
  235.         {
  236.             f = &pr_functions[i];
  237.             if (f->profile > max)
  238.             {
  239.                 max = f->profile;
  240.                 best = f;
  241.             }
  242.         }
  243.         if (best)
  244.         {
  245.             if (num < 10)
  246.                 Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name);
  247.             num++;
  248.             best->profile = 0;
  249.         }
  250.     } while (best);
  251. }
  252.  
  253.  
  254. /*
  255. ============
  256. PR_RunError
  257.  
  258. Aborts the currently executing function
  259. ============
  260. */
  261. void PR_RunError (char *error, ...)
  262. {
  263.     va_list        argptr;
  264.     char        string[1024];
  265.  
  266.     va_start (argptr,error);
  267.     vsprintf (string,error,argptr);
  268.     va_end (argptr);
  269.  
  270.     PR_PrintStatement (pr_statements + pr_xstatement);
  271.     PR_StackTrace ();
  272.     Con_Printf ("%s\n", string);
  273.     
  274.     pr_depth = 0;        // dump the stack so host_error can shutdown functions
  275.  
  276.     Host_Error ("Program error");
  277. }
  278.  
  279. /*
  280. ============================================================================
  281. PR_ExecuteProgram
  282.  
  283. The interpretation main loop
  284. ============================================================================
  285. */
  286.  
  287. /*
  288. ====================
  289. PR_EnterFunction
  290.  
  291. Returns the new program statement counter
  292. ====================
  293. */
  294. int PR_EnterFunction (dfunction_t *f)
  295. {
  296.     int        i, j, c, o;
  297.  
  298.     pr_stack[pr_depth].s = pr_xstatement;
  299.     pr_stack[pr_depth].f = pr_xfunction;    
  300.     pr_depth++;
  301.     if (pr_depth >= MAX_STACK_DEPTH)
  302.         PR_RunError ("stack overflow");
  303.  
  304. // save off any locals that the new function steps on
  305.     c = f->locals;
  306.     if (localstack_used + c > LOCALSTACK_SIZE)
  307.         PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
  308.  
  309.     for (i=0 ; i < c ; i++)
  310.         localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
  311.     localstack_used += c;
  312.  
  313. // copy parameters
  314.     o = f->parm_start;
  315.     for (i=0 ; i<f->numparms ; i++)
  316.     {
  317.         for (j=0 ; j<f->parm_size[i] ; j++)
  318.         {
  319.             ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
  320.             o++;
  321.         }
  322.     }
  323.  
  324.     pr_xfunction = f;
  325.     return f->first_statement - 1;    // offset the s++
  326. }
  327.  
  328. /*
  329. ====================
  330. PR_LeaveFunction
  331. ====================
  332. */
  333. int PR_LeaveFunction (void)
  334. {
  335.     int        i, c;
  336.  
  337.     if (pr_depth <= 0)
  338.         Sys_Error ("prog stack underflow");
  339.  
  340. // restore locals from the stack
  341.     c = pr_xfunction->locals;
  342.     localstack_used -= c;
  343.     if (localstack_used < 0)
  344.         PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
  345.  
  346.     for (i=0 ; i < c ; i++)
  347.         ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
  348.  
  349. // up stack
  350.     pr_depth--;
  351.     pr_xfunction = pr_stack[pr_depth].f;
  352.     return pr_stack[pr_depth].s;
  353. }
  354.  
  355.  
  356. /*
  357. ====================
  358. PR_ExecuteProgram
  359. ====================
  360. */
  361. void PR_ExecuteProgram (func_t fnum)
  362. {
  363.     eval_t    *a, *b, *c;
  364.     int            s;
  365.     dstatement_t    *st;
  366.     dfunction_t    *f, *newf;
  367.     int        runaway;
  368.     int        i;
  369.     edict_t    *ed;
  370.     int        exitdepth;
  371.     eval_t    *ptr;
  372.  
  373.     if (!fnum || fnum >= progs->numfunctions)
  374.     {
  375.         if (pr_global_struct->self)
  376.             ED_Print (PROG_TO_EDICT(pr_global_struct->self));
  377.         Host_Error ("PR_ExecuteProgram: NULL function");
  378.     }
  379.     
  380.     f = &pr_functions[fnum];
  381.  
  382.     runaway = 100000;
  383.     pr_trace = false;
  384.  
  385. // make a stack frame
  386.     exitdepth = pr_depth;
  387.  
  388.     s = PR_EnterFunction (f);
  389.     
  390. while (1)
  391. {
  392.     s++;    // next statement
  393.  
  394.     st = &pr_statements[s];
  395.     a = (eval_t *)&pr_globals[st->a];
  396.     b = (eval_t *)&pr_globals[st->b];
  397.     c = (eval_t *)&pr_globals[st->c];
  398.     
  399.     if (!--runaway)
  400.         PR_RunError ("runaway loop error");
  401.         
  402.     pr_xfunction->profile++;
  403.     pr_xstatement = s;
  404.     
  405.     if (pr_trace)
  406.         PR_PrintStatement (st);
  407.         
  408.     switch (st->op)
  409.     {
  410.     case OP_ADD_F:
  411.         c->_float = a->_float + b->_float;
  412.         break;
  413.     case OP_ADD_V:
  414.         c->vector[0] = a->vector[0] + b->vector[0];
  415.         c->vector[1] = a->vector[1] + b->vector[1];
  416.         c->vector[2] = a->vector[2] + b->vector[2];
  417.         break;
  418.         
  419.     case OP_SUB_F:
  420.         c->_float = a->_float - b->_float;
  421.         break;
  422.     case OP_SUB_V:
  423.         c->vector[0] = a->vector[0] - b->vector[0];
  424.         c->vector[1] = a->vector[1] - b->vector[1];
  425.         c->vector[2] = a->vector[2] - b->vector[2];
  426.         break;
  427.  
  428.     case OP_MUL_F:
  429.         c->_float = a->_float * b->_float;
  430.         break;
  431.     case OP_MUL_V:
  432.         c->_float = a->vector[0]*b->vector[0]
  433.                 + a->vector[1]*b->vector[1]
  434.                 + a->vector[2]*b->vector[2];
  435.         break;
  436.     case OP_MUL_FV:
  437.         c->vector[0] = a->_float * b->vector[0];
  438.         c->vector[1] = a->_float * b->vector[1];
  439.         c->vector[2] = a->_float * b->vector[2];
  440.         break;
  441.     case OP_MUL_VF:
  442.         c->vector[0] = b->_float * a->vector[0];
  443.         c->vector[1] = b->_float * a->vector[1];
  444.         c->vector[2] = b->_float * a->vector[2];
  445.         break;
  446.  
  447.     case OP_DIV_F:
  448.         c->_float = a->_float / b->_float;
  449.         break;
  450.     
  451.     case OP_BITAND:
  452.         c->_float = (int)a->_float & (int)b->_float;
  453.         break;
  454.     
  455.     case OP_BITOR:
  456.         c->_float = (int)a->_float | (int)b->_float;
  457.         break;
  458.     
  459.         
  460.     case OP_GE:
  461.         c->_float = a->_float >= b->_float;
  462.         break;
  463.     case OP_LE:
  464.         c->_float = a->_float <= b->_float;
  465.         break;
  466.     case OP_GT:
  467.         c->_float = a->_float > b->_float;
  468.         break;
  469.     case OP_LT:
  470.         c->_float = a->_float < b->_float;
  471.         break;
  472.     case OP_AND:
  473.         c->_float = a->_float && b->_float;
  474.         break;
  475.     case OP_OR:
  476.         c->_float = a->_float || b->_float;
  477.         break;
  478.         
  479.     case OP_NOT_F:
  480.         c->_float = !a->_float;
  481.         break;
  482.     case OP_NOT_V:
  483.         c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
  484.         break;
  485.     case OP_NOT_S:
  486.         c->_float = !a->string || !pr_strings[a->string];
  487.         break;
  488.     case OP_NOT_FNC:
  489.         c->_float = !a->function;
  490.         break;
  491.     case OP_NOT_ENT:
  492.         c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
  493.         break;
  494.  
  495.     case OP_EQ_F:
  496.         c->_float = a->_float == b->_float;
  497.         break;
  498.     case OP_EQ_V:
  499.         c->_float = (a->vector[0] == b->vector[0]) &&
  500.                     (a->vector[1] == b->vector[1]) &&
  501.                     (a->vector[2] == b->vector[2]);
  502.         break;
  503.     case OP_EQ_S:
  504.         c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string);
  505.         break;
  506.     case OP_EQ_E:
  507.         c->_float = a->_int == b->_int;
  508.         break;
  509.     case OP_EQ_FNC:
  510.         c->_float = a->function == b->function;
  511.         break;
  512.  
  513.  
  514.     case OP_NE_F:
  515.         c->_float = a->_float != b->_float;
  516.         break;
  517.     case OP_NE_V:
  518.         c->_float = (a->vector[0] != b->vector[0]) ||
  519.                     (a->vector[1] != b->vector[1]) ||
  520.                     (a->vector[2] != b->vector[2]);
  521.         break;
  522.     case OP_NE_S:
  523.         c->_float = strcmp(pr_strings+a->string,pr_strings+b->string);
  524.         break;
  525.     case OP_NE_E:
  526.         c->_float = a->_int != b->_int;
  527.         break;
  528.     case OP_NE_FNC:
  529.         c->_float = a->function != b->function;
  530.         break;
  531.  
  532. //==================
  533.     case OP_STORE_F:
  534.     case OP_STORE_ENT:
  535.     case OP_STORE_FLD:        // integers
  536.     case OP_STORE_S:
  537.     case OP_STORE_FNC:        // pointers
  538.         b->_int = a->_int;
  539.         break;
  540.     case OP_STORE_V:
  541.         b->vector[0] = a->vector[0];
  542.         b->vector[1] = a->vector[1];
  543.         b->vector[2] = a->vector[2];
  544.         break;
  545.         
  546.     case OP_STOREP_F:
  547.     case OP_STOREP_ENT:
  548.     case OP_STOREP_FLD:        // integers
  549.     case OP_STOREP_S:
  550.     case OP_STOREP_FNC:        // pointers
  551.         ptr = (eval_t *)((byte *)sv.edicts + b->_int);
  552.         ptr->_int = a->_int;
  553.         break;
  554.     case OP_STOREP_V:
  555.         ptr = (eval_t *)((byte *)sv.edicts + b->_int);
  556.         ptr->vector[0] = a->vector[0];
  557.         ptr->vector[1] = a->vector[1];
  558.         ptr->vector[2] = a->vector[2];
  559.         break;
  560.         
  561.     case OP_ADDRESS:
  562.         ed = PROG_TO_EDICT(a->edict);
  563. #ifdef PARANOID
  564.         NUM_FOR_EDICT(ed);        // make sure it's in range
  565. #endif
  566.         if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
  567.             PR_RunError ("assignment to world entity");
  568.         c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
  569.         break;
  570.         
  571.     case OP_LOAD_F:
  572.     case OP_LOAD_FLD:
  573.     case OP_LOAD_ENT:
  574.     case OP_LOAD_S:
  575.     case OP_LOAD_FNC:
  576.         ed = PROG_TO_EDICT(a->edict);
  577. #ifdef PARANOID
  578.         NUM_FOR_EDICT(ed);        // make sure it's in range
  579. #endif
  580.         a = (eval_t *)((int *)&ed->v + b->_int);
  581.         c->_int = a->_int;
  582.         break;
  583.  
  584.     case OP_LOAD_V:
  585.         ed = PROG_TO_EDICT(a->edict);
  586. #ifdef PARANOID
  587.         NUM_FOR_EDICT(ed);        // make sure it's in range
  588. #endif
  589.         a = (eval_t *)((int *)&ed->v + b->_int);
  590.         c->vector[0] = a->vector[0];
  591.         c->vector[1] = a->vector[1];
  592.         c->vector[2] = a->vector[2];
  593.         break;
  594.         
  595. //==================
  596.  
  597.     case OP_IFNOT:
  598.         if (!a->_int)
  599.             s += st->b - 1;    // offset the s++
  600.         break;
  601.         
  602.     case OP_IF:
  603.         if (a->_int)
  604.             s += st->b - 1;    // offset the s++
  605.         break;
  606.         
  607.     case OP_GOTO:
  608.         s += st->a - 1;    // offset the s++
  609.         break;
  610.         
  611.     case OP_CALL0:
  612.     case OP_CALL1:
  613.     case OP_CALL2:
  614.     case OP_CALL3:
  615.     case OP_CALL4:
  616.     case OP_CALL5:
  617.     case OP_CALL6:
  618.     case OP_CALL7:
  619.     case OP_CALL8:
  620.         pr_argc = st->op - OP_CALL0;
  621.         if (!a->function)
  622.             PR_RunError ("NULL function");
  623.  
  624.         newf = &pr_functions[a->function];
  625.  
  626.         if (newf->first_statement < 0)
  627.         {    // negative statements are built in functions
  628.             i = -newf->first_statement;
  629.             if (i >= pr_numbuiltins)
  630.                 PR_RunError ("Bad builtin call number");
  631.             pr_builtins[i] ();
  632.             break;
  633.         }
  634.  
  635.         s = PR_EnterFunction (newf);
  636.         break;
  637.  
  638.     case OP_DONE:
  639.     case OP_RETURN:
  640.         pr_globals[OFS_RETURN] = pr_globals[st->a];
  641.         pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
  642.         pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
  643.     
  644.         s = PR_LeaveFunction ();
  645.         if (pr_depth == exitdepth)
  646.             return;        // all done
  647.         break;
  648.         
  649.     case OP_STATE:
  650.         ed = PROG_TO_EDICT(pr_global_struct->self);
  651. #ifdef FPS_20
  652.         ed->v.nextthink = pr_global_struct->time + 0.05;
  653. #else
  654.         ed->v.nextthink = pr_global_struct->time + 0.1;
  655. #endif
  656.         if (a->_float != ed->v.frame)
  657.         {
  658.             ed->v.frame = a->_float;
  659.         }
  660.         ed->v.think = b->function;
  661.         break;
  662.         
  663.     default:
  664.         PR_RunError ("Bad opcode %i", st->op);
  665.     }
  666. }
  667.  
  668. }
  669.